\section{Implémentation}
	\vspace{0.5cm}
	Pour développer ce projet, nous avons choisi deux langages principaux : le \textbf{SQL} et le \textbf{PHP}. La base de donnée utilisée est de type \textbf{MySQL}, prenant en charge le moteur \textbf{INNODB} pour activer la gestion des clés étrangères.\\
	\vspace{0.5cm}	
	PHP proposant depuis la version 5 un style de programmation orienté objet, nous avons décidé d'adopter cette approche. Ceci permet d'utiliser l'extension \textit{PDO} de PHP, pour effectuer des requ\^etes en ajoutant une couche d'abstraction par rapport au type de la base de donnée. Elle apporte par la m\^eme occasion deux avantages majeurs : la récupération des données sous forme d'objet et l'utilisation de requ\^etes préparées augmentant les performances temporelles sur des requ\^etes récurrentes.\\
	\subsection{Contraintes d'intégrité des données}
		%
		%	AJouter un Create et un INSERT en exemple
		%	Expliciter le reste des commande à part
	\vspace{0.5cm}		
		Comme il a été mentionné précédemment, dans ce projet, nous avons considéré qu'aucun champ de la base de donnée n'était optionnel. Ceci implique que tous les champs des différentes tables portent la mention \verb?NOT NULL? à la création de la base de données.\\
		
		Certaines tables doivent contenir un identificateur unique, par exemple \textit{ASSOCIATION} ou \textit{INDIVIDU}. Nous avons choisi d'utiliser un entier auto-incrémenté pour modéliser cet identifiant, qui sera une clé primaire de la table.\\
		
		Pour garantir l'intégrité des données, l'utilisation de clés étrangères est un plus. En effet prenons par exemple la suppression d'un individu de la base de données.
		Si cet individu était adhérent à des associations, sa suppression en tant qu'individu implique sa suppression en tant qu'adhérent. Pour mettre en place cette logique, nous avons utilisé des contraintes sur les clés étrangères. Si une suppression survient dans une table A dont on retrouve un champ A.id comme clé étrangère dans une autre table B alors la suppression de l'élément dans A entraînera la suppression des occurrences de l'élément dans B.
			\vspace{0.5cm}
		\begin{verbatim}
			CONSTRAINT nom_de_la_contrainte FOREIGN KEY (nom_du_champ_etant_clé_étrangère) 
			REFERENCES TABLE_CONTENANT_LE_CHAMP_ETRANGER (nom_du_champ_correspondant_à_clé_étrangère)
			ON {DELETE | UPDATE}  {CASCADE | NO ACTION | SET NULL | SET DEFAULT}
		\end{verbatim}
	\vspace{0.5cm}		
		La dernière contrainte que nous avons mise en place est relative au nombre d'adhésion d'un individu. Si l'on supprime toutes les adhésions d'un individu, il n'est alors plus considéré comme un adhérent. Pour satisfaire ce besoin, un trigger (visible en section \ref{trigger}) a été mis en place sur la suppression d'une ligne d'adhésion. Il comptera les adhésions restantes de l'individu dont l'adhésion a été supprimée et s'il n'en reste aucune, une requ\^ete de suppression sera alors envoyée à la table contenant les adhérents.\\
		\paragraph{Exemple de création d'une table portant toutes les contraintes}.
		\begin{verbatim}
CREATE TABLE EVENEMENT
(
    id_evenement        INTEGER        NOT NULL	AUTO_INCREMENT	,
    id_association      INTEGER        NOT NULL			,
    id_lieu             INTEGER        NOT NULL			,
    id_frequence        INTEGER        NOT NULL			,
    nom                 VARCHAR(255)   NOT NULL			,
    date_creation       DATE           NOT NULL			,
    cout                FLOAT          NOT NULL			,
    tarif_exte          FLOAT          NOT NULL			,
    tarif_adherent      FLOAT          NOT NULL			,
    description         TEXT           NOT NULL			,
    date_debut          DATE           NOT NULL			,
    date_fin            DATE           NOT NULL			,
    nombre_place        INTEGER        NOT NULL			,		
    CONSTRAINT pk_evenement PRIMARY KEY (id_evenement)
) TYPE=INNODB;

ALTER TABLE EVENEMENT
	ADD CONSTRAINT fk1_evenement FOREIGN KEY (id_association) 
	REFERENCES ASSOCIATION (id_association)
	ON DELETE CASCADE
;

ALTER TABLE EVENEMENT
	ADD CONSTRAINT fk2_evenement FOREIGN KEY (id_lieu) 
	REFERENCES LIEU (id_lieu)
	ON DELETE CASCADE
;

ALTER TABLE EVENEMENT
	ADD CONSTRAINT fk3_evenement FOREIGN KEY (id_frequence) 
	REFERENCES FREQUENCE (id_frequence)
	ON DELETE CASCADE
;
		\end{verbatim}
	\vspace{0.5cm}		
	\subsubsection{Insertion d'un élément}
	\vspace{0.5cm}	
		Certaines tables contenant des clés étrangères, il est nécessaire de respecter un ordre d'insertion dans la base de donnée. Par exemple, comme un adhérent ne peut exister sans avoir été référencé dans les individus, il faut créer un individu, puis le déclarer en tant qu'adhérent. Les insertions pré-requises à l'ajout d'un élément spécifique sont décrites sur le graphe de dépendances (cf section \ref{dependency}).\\	
		Prenons donc l'exemple de l'ajout d'une adhésion. Les requ\^etes à effectuer sont (dans l'ordre) :
		\begin{verbatim}
			INSERT INTO `ASSOCIATION` (`id_association`, `nom`) VALUES
			(1, 'Muzik''O Rama');		
		
			INSERT INTO `INDIVIDU` (`id_individu`, `nom`, `prenom`) VALUES 
			(1, 'LAURENT', 'Isaline');
			
			INSERT INTO `ADHERENT` (`id_individu`, `email`, `filiere`, `promotion`) VALUES
			(1, 'ilaurent@enseirb-matmeca.fr', 'Informatique', 2013);
			
			INSERT INTO `ADHESION` (`id_individu`, `id_association`, `login`, `password`, 
			`cout_cotisation`, `date_inscription`) VALUES
			(1, 1, 'ilaurent', '0c4bbe50ba640e387b86b819c355622f', 25, '2011-09-12');
			
		\end{verbatim}
	\subsubsection{Suppression d'un élément}
	\vspace{0.5cm}	
		Comme nous l'avons vu précédemment la suppression d'un élément dans la base de données efface également les occurrences de toutes les tables où il appara\^it en tant que clé étrangère, gr\^ace à l'action \verb?ON DELETE CASCADE?. Cependant le cas où un adhérent n'a plus aucune adhésion n'est pas traité par ce système. Un \textit{trigger} a été mis en place pour gérer cette situation.
		
		\begin{verbatim}
			DELIMITER |
			CREATE TRIGGER REMOVE_ADHERENT_IF_NO_ADHESION 
			AFTER 
			DELETE ON ADHESION
			FOR EACH ROW
			BEGIN
			    DECLARE nb_adhesion INTEGER;
			    DECLARE sql_nb_adhesion CURSOR FOR 
			        SELECT COUNT(*) FROM ADHESION WHERE id_individu = OLD.id_individu;
			    OPEN sql_nb_adhesion;
			    FETCH sql_nb_adhesion INTO nb_adhesion;
			    IF nb_adhesion = 0 THEN
			        DELETE FROM ADHERENT WHERE id_individu = OLD.id_individu;
			    END IF;
			    CLOSE sql_nb_adhesion;
			END |
			DELIMITER ;
		\end{verbatim}
		\label{trigger}
	
	\vspace{0.5cm}	
		\subsection{Commandes SQL}	\vspace{0.5cm}

			\subsubsection{Consultation}
				\vspace{0.5cm}
				Les requ\^etes présentées ci-dessous n'apparaissent pas nécessairement dans le code source du projet. En effet, comme nous avons adopté un style de programmation orientée objet, il faut assurer la cohérence de ces derniers. Or, certaines de ces requ\^etes utilisant des jointures ne correspondent pas du point de vue des attributs des objets manipulés. C'est pourquoi certaines requ\^etes qui pourraient \^etre effectuées d'une seule traite sont segmentées dans le code source.
				\vspace{0.5cm}
				\paragraph{Associations\\}
					La requ\^ete pour récupérer les informations sur les associations est la suivante : 
					\begin{verbatim}
						SELECT id_association, nom FROM ASSOCIATION
					\end{verbatim}	
								\vspace{0.5cm}			
				\paragraph{Adhérents\\}
					Comme on peut le voir sur notre diagramme, un adhérent ne possède pas de lien direct avec l'association. Il correspond simplement à une spécification d'un individu. Les informations concernant les associations auxquelles un adhérent est inscrit se trouvent dans la table \textit{ADHESION}. Voici la commande pour lister les adhérents d'une association à une date donnée.
						\vspace{0.5cm}
					\begin{verbatim}
						SELECT id_individu, INDIVIDU.nom, INDIVIDU.prenom, email, filiere, promotion,
				 		login, password, cout_cotisation, date_inscription	FROM ADHESION 
						JOIN ADHERENT USING(id_individu)
						JOIN INDIVIDU USING(id_individu)
						WHERE id_association = :id_association 
						AND date_inscription >= :date_debut AND date_inscription <= :date_fin;
					\end{verbatim}
	\vspace{0.5cm}					
					La représentation d'une cotisation impayée s'effectue en attribuant la valeur $-1$ au champ cout\_cotisation de la table \textit{ADHESION}. La requ\^ete pour trouver les cotisations non payées est donc :
					\begin{verbatim}
						SELECT id_individu, INDIVIDU.nom, INDIVIDU.prenom, email, filiere, promotion,
						login, password, date_inscription, ASSOCIATION.nom	FROM ADHESION 
						JOIN ADHERENT USING(id_individu)
						JOIN INDIVIDU USING(id_individu)
						JOIN ASSOCIATION USING(id_association)
						WHERE cout_cotisation = -1;
					\end{verbatim}
	\vspace{0.5cm}					
				\paragraph{Evénements\\}
					La liste des personnes organisant un événement est stockée dans la table \textit{EQUIPE}. Pour récupérer l'équipe organisatrice d'un événement on utilise la requ\^ete suivante :
					\begin{verbatim}
						SELECT id_individu, nom, prenom FROM EQUIPE
						JOIN INDIVIDU USING(id_individu)
						WHERE id_evenement = :id_evenement;						
					\end{verbatim}
	\vspace{0.5cm}					
					Pour lister les participant à un événement, on utilise la m\^eme requ\^ete que précédemment mais sur la table \textit{PARTICIPANT}.
					\begin{verbatim}
						SELECT id_individu, nom, prenom FROM PARTICIPANT
						JOIN INDIVIDU USING(id_individu)
						WHERE id_evenement = :id_evenement;						
					\end{verbatim}	
				\paragraph{News\\}
	\vspace{0.5cm}					
					Pour récupérer le nombre de commentaire postés pour une news on utilise la requ\^ete suivante :
					\begin{verbatim}
						SELECT COUNT(*) FROM COMMENT_NEWS 
						WHERE id_news = :id_news";
					\end{verbatim}
	\vspace{0.5cm}					
			\subsubsection{Statistiques}
	\vspace{0.5cm}
				\paragraph{Nombre moyen de commentaire donné par un adhérent par news\\}
					
					Pour effectuer cette requ\^ete il faut tout d'abord conna\^itre le nombre de commentaires postés par un adhérent et le nombre total de news. Pour réaliser ceci, nous avons utilisé la requ\^ete suivante :
					\begin{verbatim}
						SELECT COUNT(id_commentaire) / (SELECT COUNT(id_news) FROM NEWS) FROM  COMMENT_NEWS
            			WHERE id_individu = :id_individu;
					\end{verbatim}
									
				\paragraph{Note moyenne donnée par les participants à un événement\\}
					Pour récupérer la note moyenne d'un événement, nous avons utilisé la fonction \verb?AVG()? du langage SQL, en formant la requ\^ete suivante :
					\begin{verbatim}
						SELECT AVG(note) AS avg_note FROM NOTE
    	        		WHERE id_evenement = :id_evenement;
					\end{verbatim}
				\paragraph{Classement des événements par la note donnée par les participants\\}
					
					Le classement des événements doit se faire en utilisant la note moyenne de chaque événement, ce qui nécessite de les grouper par leur identifiants pour le calcul des notes moyennes.
					
					\begin{verbatim}
						SELECT AVG( note ) AS avg_note, nom FROM NOTE
    		    		JOIN EVENEMENT USING ( id_evenement )
        				GROUP BY id_evenement
		        		ORDER BY AVG( note ) DESC;
					\end{verbatim}
				\paragraph{Classement des adhérents participant le plus aux événements\\}
					
					Le but de cette requ\^ete est de compter le nombre d'apparition des individus dans la table \textit{PARTICIPANT}, et de retourner le résultat trié par ordre décroissant par rapport au nombre d'occurrence.
					\begin{verbatim}
						SELECT id_individu, nom, prenom, COUNT(id_evenement) AS nb_participation FROM PARTICIPANT
						JOIN INDIVIDU USING(id_individu)
						GROUP BY id_individu
						ORDER BY COUNT(id_evenement) DESC
					\end{verbatim}
				\paragraph{Classement des finances des associations à une date donnée\\}
					
					Pour effectuer le classement des finances des associations à une date donnée, la requ\^ete s'appuie sur une procédure stockée nommée \textit{getfinance} dont le code est disponible dans le fichier source stored.function.getfinance.sql (dans le répertoire src/sql). Cette fonction stockée a été créée car de nombreux paramètres doivent \^etre pris en compte et ceci ne peut \^etre récupéré en une unique requ\^ete.\\
	\vspace{0.5cm}					
					Le calcul des finances d'une association se décompose comme ceci :
					\begin{enumerate}
						\item Somme des co\^uts des cotisations de ses adhérents.
						\item Somme des montant versés par les partenaires.
						\item Somme des revenus des événements :
								\begin{enumerate}
									\item Nombre d'adhérents participant à l'événement multiplié par le tarif adhérent
									\item Nombre de non adhérents participant à l'événement multiplié par le tarif non adhérent
								\end{enumerate}
						\item Somme des co\^uts de l'organisation des événements.			
					\end{enumerate}
					
					 $tresorerie = 1+2+3-4$
	\vspace{0.5cm}					 
					 La procédure stockée permet de faire ce calcul.
					 Ensuite pour classer les associations par leur finances, il suffit d'utiliser la requ\^ete :
					 \begin{verbatim}
					 	SELECT id_association, getfinance(id_association, :date) AS finance FROM ASSOCIATION
						ORDER BY finance DESC
					 \end{verbatim}	
			\subsubsection{Insertion et Mise à jour\\}		
				Comme toutes les requ\^etes d'insertions et de mise à jour d'éléments en base de données sont similaires, nous ne traiterons ici que d'un cas, celui de l'événement.
				
				\paragraph{Ajout d'un événement} : la requ\^ete permettant d'insérer un événement est la suivante :
				\begin{verbatim}
					INSERT INTO EVENEMENT
							 VALUES(null, :id_association, :id_lieu, :id_frequence, :nom, :date_creation,  
							:cout, :tarif_exte, :tarif_adherent, :description, :date_debut, :date_fin, 												:nombre_place);
				\end{verbatim}
	\vspace{0.5cm}				
				\paragraph{Modification d'un événement } : Pour modifier un événement on utilise la requ\^ete ci dessous : 
				\begin{verbatim}
					UPDATE EVENEMENT SET id_association = :id_association, id_lieu = :id_lieu,
					id_frequence = :id_frequence,	date_creation = :date_creation, nom = :nom, 
					cout = :cout, tarif_exte = :tarif_exte, tarif_adherent = :tarif_adherent,	
					description = :description, date_debut = :date_debut, date_fin = :date_fin, 
					nombre_place = :nombre_place 
					WHERE id_evenement= :id_evenement
				\end{verbatim}